#!/usr/bin/env python
# -*- coding: utf-8 -*-

import xml.sax
import math

LON = 1
LAT = 2
REF = 3
TAG = 4
ACTION = 5
VERSION = 6
USER = 7
UID = 8
CHANGESET = 9
CREATE = 0
MODIFY = 1
DELETE = 2
NODES = 0
WAYS = 1
RELATIONS = 2

class OsmData(xml.sax.ContentHandler):
  def __init__(self):
    self.nodes = {}
    self.ways = {}
    self.relations = {}
    self.currnodeid = -1
    self.currwayid = -1
    self.currrelationid = -1
    self.currentObj = None
    self.currentId = None
    self.bbox = [0, 0, 0, 0] # minlon, minlat, maxlon, maxlat
  def mergedata(self, other):
    self.nodes.update(copy.deepcopy(other.nodes))
    self.ways.update(copy.deepcopy(other.ways))
    self.relations.update(copy.deepcopy(other.relations))
  def read(self, sourceStream):
    line = ''
    iparser = xml.sax.make_parser()
    iparser.setContentHandler(self)
    while line.find('</osm>') == -1:
      line = sourceStream.readline()
      iparser.feed(line)
  def startElement(self, tag, attributes):
    if tag == "node":
      self.currentObj = {LAT: 0.0, LON: 0.0}
      for attr in attributes.items():
        if attr[0] == "id":
          self.currentId = int(attr[1])
        elif attr[0] == "version":
          self.currentObj[VERSION] = int(attr[1])
        elif attr[0] == "changeset":
          self.currentObj[CHANGESET] = int(attr[1])
        elif attr[0] == "uid":
          self.currentObj[UID] = int(attr[1])
        elif attr[0] == "lat":
          self.currentObj[LAT] = float(attr[1])
          if self.currentObj[LAT] < self.bbox[1] or self.bbox[1] == 0:
            self.bbox[1] = self.currentObj[LAT]
          if self.currentObj[LAT] > self.bbox[3] or self.bbox[3] == 0:
            self.bbox[3] = self.currentObj[LAT]
        elif attr[0] == "lon":
          self.currentObj[LON] = float(attr[1])
          if self.currentObj[LON] < self.bbox[0] or self.bbox[0] == 0:
            self.bbox[0] = self.currentObj[LON]
          if self.currentObj[LON] > self.bbox[2] or self.bbox[2] == 0:
            self.bbox[2] = self.currentObj[LON]
        elif attr[0] == "user":
          self.currentObj[USER] = attr[1]
      self.currentObj[TAG] = {}
    elif tag == "way":
      self.currentObj = {}
      for attr in attributes.items():
        if attr[0] == "id":
          self.currentId = int(attr[1])
        elif attr[0] == "version":
          self.currentObj[VERSION] = int(attr[1])
        elif attr[0] == "changeset":
          self.currentObj[CHANGESET] = int(attr[1])
        elif attr[0] == "uid":
          self.currentObj[UID] = int(attr[1])
        elif attr[0] == "user":
          self.currentObj[USER] = attr[1]
      self.currentObj[TAG] = {}
      self.currentObj[REF] = []
    elif tag == "relation":
      self.currentObj = {}
      for attr in attributes.items():
        if attr[0] == "id":
          self.currentId = int(attr[1])
        elif attr[0] == "version":
          self.currentObj[VERSION] = int(attr[1])
        elif attr[0] == "changeset":
          self.currentObj[CHANGESET] = int(attr[1])
        elif attr[0] == "uid":
          self.currentObj[UID] = int(attr[1])
        elif attr[0] == "user":
          self.currentObj[USER] = attr[1]
      self.currentObj[TAG] = {}
      self.currentObj[REF] = [[], [], []] # [Nodes, Ways, Relations]
    elif tag == "tag":
      self.currentObj[TAG][attributes.get("k")] = attributes.get("v")
    elif tag == "nd":
      for attr in attributes.items():
        if attr[0] == "ref":
          self.currentObj[REF].append(int(attr[1]))
    elif tag == "member":
      mtype = attributes.get("type")
      if mtype == "node":
        self.currentObj[REF][NODES].append((int(attributes.get("ref")), attributes.get("role")))
      elif mtype == "way":
        self.currentObj[REF][WAYS].append((int(attributes.get("ref")), attributes.get("role")))
      elif mtype == "relation":
        self.currentObj[REF][RELATIONS].append((int(attributes.get("ref")), attributes.get("role")))
  def endElement(self, tag):
    if self.currentId != None:
      if tag == "node":
        self.nodes[self.currentId] = self.currentObj
      elif tag == "way":
        self.ways[self.currentId] = self.currentObj
      elif tag == "relation":
        self.relations[self.currentId] = self.currentObj

